﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ZoneFiveSoftware.Common.Visuals.Fitness;
using ZoneFiveSoftware.Common.Data.Fitness;
using System.Reflection;
using System.Windows.Forms.DataVisualization.Charting;

namespace HackersDiet
{
    public partial class UserControl1 : UserControl
    {
        #region Members

        private Dictionary<PropertyInfo, Dictionary<DateTime, float>> propertyValues = new Dictionary<PropertyInfo, Dictionary<DateTime, float>>();
        private Dictionary<PropertyInfo, DataSeriesProperties> dataSeriesProperties = new Dictionary<PropertyInfo, DataSeriesProperties>();
        private List<PropertyInfo> selectedNodes = new List<PropertyInfo>();
        //private Chart chart2 = new Chart();

        #endregion

        #region Private Members

        private void Initialise()
        {
            IApplication application = Plugin.GetApplication();
            this.treeView1.Nodes["Chart"].Tag = this.chart;
          
            try
            {
                #region Find interesting IAthleteProperties

                Type i = typeof(IAthleteInfoEntry);
                System.Reflection.PropertyInfo[] blah = i.GetProperties();

                foreach (System.Reflection.PropertyInfo pi in blah)
                {
                    if (pi.PropertyType == typeof(float) || pi.PropertyType == typeof(int) || pi.PropertyType == typeof(double))
                    {
                        this.propertyValues.Add(pi, new Dictionary<DateTime, float>());
                        this.dataSeriesProperties.Add(pi, new DataSeriesProperties());

                        TreeNode tn = new TreeNode(pi.Name);
                        tn.Tag = pi;
                        this.treeView1.Nodes["Chart"].Nodes.Add(tn);
                        TreeNode tnActual = new TreeNode("Actual");
                        TreeNode tnAverage = new TreeNode("Average");
                        tn.Nodes.Add(tnActual);
                        tnActual.Tag = new Series(pi.Name + ":Actual");
                        tn.Nodes.Add(tnAverage);
                        tnAverage.Tag = new Series(pi.Name + ":Average");
                    }
                }

                this.treeView1.Sort();

                #endregion

                #region Load data for those "interesting" properties

                if (application.Logbook.Athlete.InfoEntries.EntryDates.Count == 0)
                    throw new ApplicationException("No athlete info in logbook.");

                foreach (KeyValuePair<PropertyInfo, Dictionary<DateTime, float>> kvp in this.propertyValues)
                {
                    foreach (DateTime dt in application.Logbook.Athlete.InfoEntries.EntryDates)
                    {
                        float value = float.NaN;
                        
                        object tmp = kvp.Key.GetValue(application.Logbook.Athlete.InfoEntries.EntryForDate(dt), null);

                        if (tmp is float)
                            value = (float)tmp;
                        else if (tmp is int)
                            value = (float)((int)tmp);
                        else if (tmp is double)
                            value = (float)((double)tmp);

                        if (!float.IsNaN(value) && !float.IsInfinity(value) && value > 0.0f)
                        {
                            kvp.Value[dt] = value;
                        }
                    }
                }

                #endregion
            }
            catch (Exception e)
            {
                throw new Exception("HDView.cs:ShowPage() - Problem creating graph", e);
            }
        }

        #endregion

        public void Display()
        {
            // clear the chart data series and axis
            this.chart.Series.Clear();
            //this.chart..Clear();

            //foreach (PropertyInfo propInfo in this.selectedNodes)
            //{
            //    //DataSeriesProperties dsp = this.dataSeriesProperties[propInfo];

            //    if (dsp.ActualChartDataSeries == null || dsp.AverageChartDataSeries == null)
            //        continue;

            //    if (dsp.ShowAverage)
            //    {
            //        this.chart.Series.Add(dsp.AverageChartDataSeries);
            //    }
            //    if (dsp.ShowActual)
            //    {
            //        this.chart.Series.Add(dsp.ActualChartDataSeries);
            //    }

            //    //if (this.chart.YAxis != dsp.ActualChartDataSeries.ValueAxis && !this.chart.YAxisRight.Contains(dsp.ActualChartDataSeries.ValueAxis))
            //    //    this.chart.YAxisRight.Add(dsp.ActualChartDataSeries.ValueAxis);
            //}

            //this.chart.AutozoomToData(true);
            this.chart.Refresh();
        }

        public UserControl1()
        {
            InitializeComponent();

            this.chart.AutoSize = true;
            this.chart.Dock = DockStyle.Fill;
            //this.chart.XAxis.Formatter = new Formatter.DaysToDate(DateTime.Today);
            this.splitContainer1.Panel2.Controls.Add(this.chart);

            Initialise();

            this.startDatePicker.Value = DateTime.Today.Subtract(new TimeSpan(30, 0, 0, 0, 0));
            this.endDatePicker.Value = DateTime.Today;

            //this.chart.AutozoomToData(true);
        }

        private void OnUpdateButtonClicked(object sender, EventArgs e)
        {
            this.selectedNodes.Clear();

            foreach (TreeNode node in this.treeView1.Nodes[0].Nodes)
            {
                if (node.Checked == true)
                {
                    node.Checked = false;
                    node.Checked = true;
                }
            }

            this.Display();
        }

        private void AfterSelectTreeNode(object sender, TreeViewEventArgs e)
        {
            if (sender == null)
                return;

            //TreeView treeView = (TreeView)sender;

            //if (treeView.SelectedNode.Text == "Chart" && treeView.SelectedNode.Tag != null)
            //{
            //    this.propertyGrid1.SelectedObject = treeView.SelectedNode.Tag;
            //}
            //else if (treeView.SelectedNode != null && treeView.SelectedNode.Tag != null)
            //{
            //    this.propertyGrid1.SelectedObject = (object)this.dataSeriesProperties[(PropertyInfo)treeView.SelectedNode.Tag];
            //    this.propertyGrid1.Tag = treeView.SelectedNode.Tag;
            //}
            //else
            //{
            //    this.propertyGrid1.SelectedObject = null;
            //}
        }

        private void AfterCheckTreeNode(object sender, TreeViewEventArgs e)
        {
            if (sender == null)
                return;

            //TreeView treeView = (TreeView)sender;

            //treeView.SelectedNode = e.Node;

            //if (treeView.SelectedNode.Checked == true && e.Node.Tag != null)
            //{
            //    PropertyInfo propInfo = (PropertyInfo)e.Node.Tag;

            //    Dictionary<DateTime, float> data = this.propertyValues[propInfo];

            //    this.selectedNodes.Add(propInfo);

            //    // add the data
            //    //if (!this.dataSeriesProperties.ContainsKey(propInfo))
            //    {
            //        //IEnumerable<KeyValuePair<DateTime, float>> selectedDates = data.Where(athInfoEntry => athInfoEntry.Key >= this.startDatePicker.Value && athInfoEntry.Key <= this.endDatePicker.Value);
            //        IEnumerable<KeyValuePair<DateTime, float>> selectedDates = data.Where(athInfoEntry => athInfoEntry.Key >= DateTime.MinValue && athInfoEntry.Key <= DateTime.MaxValue);

            //        if (selectedDates.Count() == 0)
            //            return;

            //        DataSeriesProperties dsp = this.dataSeriesProperties[propInfo];
            //        //dsp.AverageChartDataSeries = new Series(propInfo.Name + " - Average");
            //        //dsp.ActualChartDataSeries = new Series(propInfo.Name);

            //        Axis axis = null;
                    
            //        if (this.selectedNodes.Count == 1)
            //        {
            //            axis = new Axis(this.chart.ChartAreas[0], AxisName.Y);
            //        }
            //        else if (this.selectedNodes.Count > 1)
            //        {
            //            axis = new Axis(this.chart.ChartAreas[0], AxisName.Y2);
            //            //dsp.AverageChartDataSeries.YAxisType = AxisType.Secondary;
            //            //dsp.ActualChartDataSeries.YAxisType = AxisType.Secondary;
            //        }

            //        //axis.Enabled = AxisEnabled.;
            //        axis.Title = propInfo.Name;
            //        axis.Minimum = double.NaN;
            //        axis.Maximum = double.NaN;
            //        axis.IsStartedFromZero = false;
            //        axis.ScaleView.Zoomable = true;

            //        //StripLine stripLine = new StripLine();
            //        //stripLine.StripWidth = 2;
            //        //stripLine.StripWidthType = DateTimeIntervalType.Days;

            //        //stripLine.BackColor = Color.FromArgb(120, Color.Gray);
            //        //stripLine.IntervalOffset = -1;
            //        //stripLine.IntervalOffsetType = DateTimeIntervalType.Days;
            //        //stripLine.Interval = 1;
            //        //stripLine.IntervalType = DateTimeIntervalType.Weeks;
            //        //this.chart.ChartAreas[0].AxisX.StripLines.Add(stripLine);

            //        //axis.Label = propInfo.Name;
            //        this.chart.ChartAreas[0].AxisY.ScaleBreakStyle.StartFromZero = StartFromZero.No;
            //        this.chart.ChartAreas[0].AxisY.ScaleBreakStyle.Enabled = true;
            //        //dsp.AverageChartDataSeries.XValueType = ChartValueType.Date;
            //        //dsp.AverageChartDataSeries.ChartType = SeriesChartType.Line;
                    
                    
            //        //dsp.ActualChartDataSeries.ChartType = SeriesChartType.Line;
            //        //dsp.ActualChartDataSeries.XValueType = ChartValueType.Date;
                    

            //        //DateTime lastDate = DateTime.MinValue;
            //        //float runningAvg = 0.0f;
            //        //float lastWeight = 0.0f;

            //        //lastDate = selectedDates.First().Key;
            //        //runningAvg = selectedDates.First().Value;
            //        //dsp.AverageChartDataSeries.Points.Add(new DataPoint(lastDate.ToOADate(), (float)runningAvg));

            //        //foreach (KeyValuePair<DateTime, float> athInfoEntry in selectedDates)
            //        //{
            //        //    dsp.ActualChartDataSeries.Points.Add(new DataPoint(athInfoEntry.Key.ToOADate(), (float)athInfoEntry.Value));

            //        //    float slope = (athInfoEntry.Value - lastWeight) / (athInfoEntry.Key != lastDate ? (athInfoEntry.Key - lastDate).Days : 1);

            //        //    for (int j = 1; lastDate.AddDays((double)j) <= athInfoEntry.Key; j++)
            //        //    {
            //        //        runningAvg = dsp.Weight * runningAvg + (1 - dsp.Weight) * (lastWeight + j * slope);
            //        //        dsp.AverageChartDataSeries.Points.Add(new DataPoint(lastDate.AddDays((double)j).ToOADate(), (float)runningAvg));
            //        //    }

            //        //    lastDate = athInfoEntry.Key;
            //        //    lastWeight = athInfoEntry.Value;
            //        //}
            //    }
            //}
            //else
            //{
            //    // Remove the data
            //    if (this.selectedNodes.Contains((PropertyInfo)e.Node.Tag))
            //    {
            //        this.selectedNodes.Remove((PropertyInfo)e.Node.Tag);
            //    }
            //}

            this.Display();
        }

        private void OnPropertyValueChanged(object s, PropertyValueChangedEventArgs e)
        {
            if (s == null)
                return;

            PropertyGrid pg = (PropertyGrid)s;

            if (pg.SelectedObject.GetType() == typeof(PropertyInfo))
                this.dataSeriesProperties[(PropertyInfo)pg.Tag] = (DataSeriesProperties)pg.SelectedObject;
            //else if (pg.Tag.GetType() == typeof(ChartArea))
            //    this.c

            this.Display();
        }
    }
}
